package com.ht.api.callback.impl.official;

import javax.sql.DataSource;

import cn.hutool.json.JSONUtil;
import com.ht.api.callback.CallbackFunction;
import com.ht.api.constant.CacheConstants;
import com.ht.api.constant.KfSessionStatus;
import com.ht.api.constant.Message;
import com.ht.api.db.Db;
import com.ht.api.db.DbConfig;
import com.ht.api.db.DbList;
import com.ht.api.db.Entity;
import com.ht.api.db.util.HtUtil;
import com.ht.api.db.util.RedisUtil;
import com.ht.api.service.KfService;
import com.ht.api.service.OfficialService;
import com.ht.api.websocket.WebSocket;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信公众号：消息接收
 * @author asq
 * @createTime 2025年4月8日 17:47:35
 */
@Slf4j
public class MessageCallbackFunction implements CallbackFunction {
    
    private WebSocket webSocket;

	@Override
	public void execute(String appid, Entity callback, JSONObject params) {
		// 获取应用对应的数据源
		DataSource ds = getTenantDs(appid);
		
		// 提取用户消息
		String openid = params.getStr("FromUserName");
		String msgId = params.getStr("MsgId");
		String sendTime = HtUtil.formatTimeString(params.getStr("CreateTime"));

		// 查询客服会话
		Entity kfSession = Db.createSqlParser("kf_session")
				.where("openid", openid)
				.findOne(ds);
		if (kfSession == null) {
			kfSession = Db.createEntity("kf_session");
			kfSession.set("openid", openid);
			kfSession.set("status", KfSessionStatus.WAIT);
			kfSession.set("send_time", sendTime);
			kfSession.set("appid", appid);
			kfSession.set("type", 1);
			Db.insert(ds, kfSession);
			log.info("[MessageCallbackFunction]首次消息到达，创建公众号会话完成~");
		}
		
		// 写入kfMessage表
		Entity kfMessage = Db.createEntity("kf_message");
		kfMessage.set("msgid", msgId);
		kfMessage.set("session_id", kfSession.getMainId());
		kfMessage.set("openid", openid);
		kfMessage.set("send_time", sendTime);
		kfMessage.set("origin", 3);
		kfMessage.set("msgtype", params.getStr("MsgType"));
		kfMessage.set("content", formatContent(params).toString());
		kfMessage.set("appid", appid);
		Db.insert(ds, kfMessage);
		
		// 更新会话表
		Entity kfSessionUpdate = Db.createEntity("kf_session");
		kfSessionUpdate.setMainId(kfSession.getMainId());
		kfSessionUpdate.set("msg", OfficialService.formatMsg(params));
		kfSessionUpdate.set("first_msg_time", sendTime);
		kfSessionUpdate.set("last_msg_time", sendTime);
		Integer sessionMsgCnt = kfSession.getInt("session_msg_cnt");
		kfSessionUpdate.set("session_msg_cnt", sessionMsgCnt != null ? -sessionMsgCnt : 0);
		kfSessionUpdate.set("customer_msg_cnt", 1);
		if (kfSession.getInt("status") == KfSessionStatus.OVER) {
			kfSessionUpdate.set("status", KfSessionStatus.RESET);
		}
		Db.insert(ds, kfSessionUpdate);
		
		// 更新会话与客服关联表kf_session_servicer_relation
		Entity kfSessionServicerRelationEntity = Db.createSqlParser("kf_session_servicer_relation")
				.where("session_id", kfSession.getMainId())
				.order("start_time", "desc").limit(1).findOne(ds);
		if (kfSessionServicerRelationEntity != null) {
			Entity kfSessionServicerRelation = Entity.create("kf_session_servicer_relation");
			kfSessionServicerRelation.setMainId(kfSessionServicerRelationEntity.getMainId());
			kfSessionServicerRelation.set("first_msg_time", sendTime);
			kfSessionServicerRelation.set("last_msg_time", sendTime);
			kfSessionServicerRelation.set("customer_msg_cnt", 1);
			kfSessionServicerRelation.set("last_customer_msg_time", sendTime);
			Db.insert(ds, kfSessionServicerRelation);
		}
		
		// 推送消息
		getWebSocket().sendMessage(Message.createMsg(Message.MESSAGE, kfMessage), getSessionUserid(ds, kfSession));
		
		// 启动监控消息过期的任务
		KfService.monitorSessionTask(ds, kfSession);
		
		log.info("收到公众号回调：{}", params.toString());
	}

	public JSONObject formatContent (JSONObject params) {
		String msgtype = params.getStr("MsgType");

		JSONObject content = JSONUtil.createObj();
		content.set("msgtype", msgtype);
		switch (msgtype) {
			case "text":
				content.putByPath("text.content", params.getStr("Content"));
				break;

			case "image":
				content.putByPath("image.attach_url", params.getStr("PicUrl"));
				break;

			case "voice":

				String voiceAttachUrl = OfficialService.uploadFileToAliyun(params.getStr("MediaId"));
				content.putByPath("voice.attach_url", voiceAttachUrl);
				break;

			case "video":
				String voideAttachUrl = OfficialService.uploadFileToAliyun(params.getStr("MediaId"));
				content.putByPath("video.attach_url", voideAttachUrl);
				break;
		}

		return content;
	}

	/**
	 * 获取会话对应的接待人员或待接待人员列表
	 * @param ds
	 * @param kfSession
	 * @return
	 */
	private String[] getSessionUserid(DataSource ds, Entity kfSession) {
		if (kfSession == null) {
			return null;
		}
		
		// 如果会话已分配接待人员，则返回接待人员关联的登陆人员ID
		String userid = kfSession.getStr("userid");
		if (StrUtil.isNotBlank(userid)) {
			return new String[] {userid};
		}
		
		// 如果会话还没有分配任何接待人员，则返回该会话对应的客服帐号的所有接待人员ID
		String sceneParam = kfSession.getStr("scene_param");
		String sql = """
				select userid from fan_user_team_relation where team_id in(
				  select team_id from position_channel where state=? and sys_deleted=1
				) and sys_deleted=1 and status=0
				""";
		DbList list = Db.query(ds, sql, sceneParam);
		return list.stream().map(b -> b.getStr("userid")).toArray(String[]::new);
	}

	/**
	 * 返回应用的所属租户库数据源
	 * @param appid
	 * @return
	 */
	private DataSource getTenantDs(String appid) {
		Entity entity = RedisUtil.get(CacheConstants.KEY_APP + appid);
		return DbConfig.useTenantDb(entity.getLong("tenant_id"));
	}
    
    /**
     * 获取websocket对象
     * @return
     */
    private WebSocket getWebSocket() {
    	if (webSocket == null) {
    		webSocket = SpringUtil.getBean(WebSocket.class);
    	}
    	return webSocket;
    }

}
